<?php 
/**
 * getModuleName($default = 'Index')
 * getControllerName($default = 'Index')
 * getActionName($default = '')
 * getModuleKey()
 * getBaseSiteurl()
 * getControllerKey()
 * getActionKey() 
 * setModuleKey($key = '')
 * setControllerKey($key = '')
 * setActionKey($key = '')
 * setModuleName($value = '')
 * setControllerName($value = '')
 * setActionName($value = '') 
 * getUserParams() 
 * getUserParam($key, $default = '')
 * setParam($key, $value = null)
 * clearParams()
 * getParam($paramKey, $default = '')
 * GET($name, $default = NULL)
 * POST($name, $default = NULL)
 * REQUEST($name, $default = NULL)
 * setRequestDefaultMode($mode)
 * getAction()
 * getSiteUrl() 
 *
 * Var:
 *   baseSiteurl
 */

class __REQUEST
{
	private static $_instance;
	public $ip_addr;
	public $module;
	private $_moduleKey = 'module';
	private $controller;
	private $_controllerKey = 'controller';
	private $action;
	private $_actionKey = 'action';
	private $_params = array();
	protected $_aliases = array();
	
	public $is_register_globals = false;
	public $is_magic_quotes_gpc = false;
	public $is_filter = false;
	public $requestUri;
	public $baseSiteurl;
	public $serverName;
	public $serverProtocol;
	public $serverPort;
	public $myCurrentDomain;
	public $headerstatus;
	public $siteUrl;
	public $referer;
	public $userAgent;
	public $requestDefaultMode = 'request';
	public $allowRequestMods = array('get', 'post', 'request', 'cookie', 'session', 'env', 'server');
	

		public function __construct() {
		$this->ip_addr = ip2long($_SERVER['REMOTE_ADDR']);
		if (strtolower(ini_get('register_globals')) == 'on' OR ini_get('register_globals') == '1') {
			$this->is_register_globals = true;
		}
		if (function_exists('get_magic_quotes_gpc')) {
			if (get_magic_quotes_gpc()) $this->is_magic_quotes_gpc = true;
		}
		if (extension_loaded( 'filter') AND filter_id(ini_get('filter.default')) !== FILTER_UNSAFE_RAW) {
			$this->is_filter = true;
		}
		$_REQUEST = array_merge ($_POST, array_diff_key($_GET, $_POST));
		$this->_fixGET($_GET);

		$documentRoot = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : '';
		if (!empty($documentRoot)) $documentRoot = str_replace(DIRECTORY_SEPARATOR, '/', $documentRoot);
		if (!empty($documentRoot)) $documentRoot = preg_replace("/[\/]+$/", '', $documentRoot);

		if (!$this->baseSiteurl) {
			$this->_getBaseSiteurl();
		}

		$this->serverName = $_SERVER['SERVER_NAME'];

		if (!$this->serverProtocol) {
			$this->_getServerProtocol();
		}

		$this->serverPort = ($_SERVER['SERVER_PORT'] == "80") ? '' : (':' . $_SERVER['SERVER_PORT']);
		$this->myCurrentDomain = $this->serverProtocol . '://' . $this->serverName . $this->serverPort;
		$this->headerstatus = (substr(php_sapi_name(), 0, 3 ) == 'cgi' ) ? 'Status:' : $_SERVER['SERVER_PROTOCOL'];
		$this->siteUrl = $this->myCurrentDomain . $this->baseSiteurl;

		if (!$this->requestUri) {
			$this->_getRequestUri();
		}

		$this->referer = $this->_getEnv(array('HTTPreferer', 'Referer'));
		if (!$this->userAgent) {
			$this->_getUserAgent();
		}

		$this->_params = $this->_loadParams();

		// -------
		$this->module = $this->getParam($this->getModuleKey());
		$this->controller = $this->getParam($this->getControllerKey());
		$this->action = $this->getParam($this->getActionKey());
	}

	private function _loadParams() {
		$params = array();
		if (in_array('get', $this->allowRequestMods)) {
			foreach($_GET as $getName => $getValue) {
				$params[$getName] = $this->_securityGet($getValue);
			}
		}
		if (in_array('post', $this->allowRequestMods)) {
			foreach($_POST as $postName => $postValue) {
				$params[$postName] = $this->_securityPost($postValue);
			}
		}

		return $params;
	}

	

	public function getModuleName($default = 'Index') {
		$this->module = $this->getParam($this->getModuleKey());

		$this->module = preg_replace('/^[^A-z0-9-_.]+$/i', '', $this->module);
		$this->module = ucfirst($this->module);

		if (!empty($this->module)) {
			return $this->module;
		}

		return $default;
	}

	public function getControllerName($default = 'Index') {
		$this->controller = $this->getParam($this->getControllerKey());

		$this->controller = preg_replace('/^[^A-z0-9-_.]+$/i', '', $this->controller);
		$this->controller = ucfirst($this->controller);

		if (!empty($this->controller)) {
			return $this->controller;
		}

		return $default;
	}

	public function getActionName($default = '') {
		$this->action = $this->getParam($this->getActionKey());

		$this->action = preg_replace('/^[^A-z0-9-_.]+$/i', '', $this->action);
		$this->action = ucfirst($this->action);

		if (!empty($this->action)) {
			return $this->action;
		}

		return $default;
	}

	public function getModuleKey() {
		return $this->_moduleKey;
	}

	public function getBaseSiteurl() {
		return $this->baseSiteurl;
	}

	public function getControllerKey() {
		return $this->_controllerKey;
	}

	public function getActionKey() {
		return $this->_actionKey;
	}

	public function setModuleKey($key = '') {
		$this->_moduleKey = $key;
	}

	public function setControllerKey($key = '') {
		$this->_controllerKey = $key;
	}

	public function setActionKey($key = '') {
		$this->_actionKey = $key;
	}

	public function setModuleName($value = '') {
		$this->module = $value;
		return $this;
	}

	public function setControllerName($value = '') {
		$this->controller = $value;
		return $this;
	}

	public function setActionName($value = '') {
		$this->action = $value;
		return $this;
	}

	public function getUserParams() {
		return $this->_params;
	}

	public function getUserParam($key, $default = '') {
		if (isset($this->_params[$key])) {
			return $this->_params[$key];
		}

		return $default;
	}

	public function setParam($key, $value = null) {
		$key = (string) $key;

		if ($value === NULL AND isset($this->_params[$key])) {
			unset($this->_params[$key]);
		} elseif ($value !== NULL) {
			$this->_params[$key] = $value;
		}

		return $this;
	}

	public function clearParams() {
		$this->_params = array();
		return $this;
	}

	public function getParam($paramKey, $default = '') {
		$key = (string)$paramKey;
		if (isset($this->_params[$key])) {
			return $this->_params[$key];
		}

		return $default;
	}

	public static function getInstance() {
		if (!self::$_instance) self::$_instance = new self();

		return self::$_instance;
	}

	public function GET($name, $default = NULL) {
		return $this->_getValue($name, 'get', $default);
	}

	public function POST($name, $default = NULL) {
		return $this->_getValue($name, 'post', $default);
	}

	public function REQUEST($name, $default = NULL) {
		return $this->_getValue($name, 'request', $default);
	}

	public function setRequestDefaultMode($mode) {
		$this->requestDefaultMode = strtolower(trim($mode));
	}

	public function getAction() {
		$module = $this->GET('module', 'Index');
		$view = $this->GET('view', 'Index');

		$module = preg_replace('/([^A-z0-9\_-]+)/', '', $module);
		$view = preg_replace('/([^A-z0-9\_-]+)/', '', $view);

//		$this->_checkModuleAndViewExist($module, $view);

		// $this->_checkAndFixActionRequest($view, __VIEWS::getInstance()->getAllViews());
		return array('module' => $module, 'view' => $view);
	}

	public static function getClass($a = array('module' => 'Index', 'view' => 'Index')) {
		return array('view' => 'view' . $a['module'], 'action' => 'action' . $a['view']);
	}

	public function getSiteUrl() {
		return $this->siteUrl;
	}

	private function _getRequestUri($requestUri = null) {
		if ($requestUri === null) {
		if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
			$requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
		} elseif (
		// IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem)
			isset($_SERVER['IIS_WasUrlRewritten'])
			&& $_SERVER['IIS_WasUrlRewritten'] == '1'
			&& isset($_SERVER['UNENCODED_URL'])
			&& $_SERVER['UNENCODED_URL'] != ''
			) {
				$requestUri = $_SERVER['UNENCODED_URL'];
			} elseif (isset($_SERVER['REQUEST_URI'])) {
				$requestUri = $_SERVER['REQUEST_URI'];
				// Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path
				$schemeAndHttpHost = $this->serverProtocol . '://' . $this->serverName;
				if (strpos($requestUri, $schemeAndHttpHost) === 0) {
					$requestUri = substr($requestUri, strlen($schemeAndHttpHost));
				}
			} elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
				$requestUri = $_SERVER['ORIG_PATH_INFO'];
				if (!empty($_SERVER['QUERY_STRING'])) {
					$requestUri .= '?' . $_SERVER['QUERY_STRING'];
				}
			} else {
				return '';
			}
		} elseif (!is_string($requestUri)) {
			return '';
		} else {
			// Set GET items, if available
			if (false !== ($pos = strpos($requestUri, '?'))) {
				// Get key => value pairs and set $_GET
				$query = substr($requestUri, $pos + 1);
				parse_str($query, $vars);
				$this->setQuery($vars);
			}
		}

		$this->requestUri = $requestUri;
		return $this;
	}


	private function _getUserAgent() {
		return $this->userAgent = substr( htmlspecialchars((string)$this->_getEnv('HTTP_USER_AGENT')), 0, 255);
	}

	private function _getServerProtocol() {
		$serverProtocol = $_SERVER['SERVER_PROTOCOL'];
		$serverProtocol = preg_replace('/^([^\/]+)\/*(.*)$/', '\\1', $serverProtocol);
		$serverProtocol = strtolower($serverProtocol);

		if ($this->_getEnv('HTTPS') == 'on') {
			$serverProtocol .= 's';
		}

		return $this->serverProtocol = $serverProtocol;
	}

	private function _getBaseSiteurl() {
		$path = pathinfo( $_SERVER['PHP_SELF'], PATHINFO_DIRNAME );
		if (empty($path)) {
			$path = '/';
		}

		return $this->baseSiteurl = $path;
	}

	public function setQuery($spec, $value = null) {
		if ((null === $value) && !is_array($spec)) {
			throw new Exception_Request('Invalid value passed to setQuery(); must be either array of values or key/value pair');
		}
		if ((null === $value) && is_array($spec)) {
			foreach ($spec as $key => $value) {
				$this->setQuery($key, $value);
			}
			return $this;
		}
		$_GET[(string) $spec] = $value;
		return $this;
	}

	private function _getValue($name, $mode = NULL, $default = NULL) {
		$modes = $this->_parseMode($mode);
		foreach ($modes as $mode) {
			switch ($mode) {
				case 'get': if (array_key_exists($name, $_GET)) return $_GET[$name]; break;
				case 'post': if (array_key_exists($name, $_POST)) return ( (empty($_POST[$name]) OR is_numeric($_POST[$name]))? $_POST[$name] : $this->_securityPost($_POST[$name])); break;
				case 'request':
					if (array_key_exists($name, $_POST)) return ((empty($_POST[$name]) OR is_numeric($_POST[$name]))? $_POST[$name] : $this->_securityPost($_POST[$name]));
					elseif (array_key_exists($name, $_GET)) return $_GET[$name]; break;
				case 'env': if (array_key_exists($name, $_ENV)) return $_ENV[$name]; break;
				case 'server': if ( array_key_exists( $name, $_SERVER ) ) return $_SERVER[$name]; break;
			}
		}
		return $default;
	}

	private function _securityPost($value) {
		if (is_array($value)) {
			$keys = array_keys($value);
			foreach ($keys as $keyword) {
				$value[$keyword] = $this->_securityPost( $value[$keyword] );
			}
		}
		else {
			$value = preg_replace("/\t+/", " ", $value);
			unset($matches);
			preg_match_all('/<!\[cdata\[(.*?)\]\]>/is', $value, $matches);
			$value = str_replace($matches[0], $matches[1], $value);
			$value = str_replace(array("'", '"', '<', '>'), array("&#039;", "&quot;", "&lt;", "&gt;"), $value );
			$value = str_replace(array("[:", ":]", "{:", ":}"), array('"', '"', "<", '>'), $value);
			$value = trim($value);
		}
		return $value;
	}

	private function _securityGet($value) {
		if (is_array($value)) {
			$keys = array_keys($value);
			foreach ($keys as $keyword) {
				$value[$keyword] = $this->_securityGet($value[$keyword]);
			}
		}
		else {
			$value = preg_replace("/\t+/", " ", $value);
			unset($matches);
			preg_match_all('/<!\[cdata\[(.*?)\]\]>/is', $value, $matches);
			$value = str_replace($matches[0], $matches[1], $value);
			$value = str_replace(array("'", '"', '<', '>'), array("&#039;", "&quot;", "&lt;", "&gt;"), $value );
			$value = str_replace(array("[:", ":]", "{:", ":}"), array('"', '"', "<", '>'), $value);
			$value = trim($value);
		}
		return $value;
	}

	private function _fixGET(&$var) {
		$array_keys = array_keys($var);
		foreach ($array_keys as $keyword) {
			if (is_array($var[$keyword])) $this->fixQuery($var[$keyword]);
			elseif (is_string($var[$keyword])) {
				if ( $this->isMagicQuotesGpc ) $var[$keyword] = stripslashes($var[$keyword]);
				if (!empty($var[$keyword]) AND !is_numeric($var[$keyword])) {
					$var[$keyword] = str_replace(array( "\t", "\r", "\n", "../"), "", $var[$keyword]);
					$var[$keyword] = $this->_unhtmlentities($var[$keyword]);
					unset( $matches );
					preg_match_all('/<!\[cdata\[(.*?)\]\]>/is', $var[$keyword], $matches);
					$var[$keyword] = str_replace($matches[0], $matches[1], $var[$keyword]);
					$var[$keyword] = strip_tags($var[$keyword]);
					$var[$keyword] = str_replace(array("'", '"', '<', '>'), array("&#039;", "&quot;", "&lt;", "&gt;"), $var[$keyword]);
					$var[$keyword] = trim($var[$keyword]);
				}
			}
		}
	}

	private function _parseMode($mode) {
		if (empty($mode)) return array($this->requestDefaultMode);
		$mode = explode(",", $mode);
		$mode = array_map('trim', $mode);
		$mode = array_map('strtolower', $mode);
		$mode = array_intersect($this->allowRequestMods, $mode);
		if (empty($mode)) return array($this->requestDefaultMode);
		return array_values($mode);
	}

	private function _getEnv($envKey) {
		if (!is_array($envKey)) $envKey = array($envKey);
		foreach ($envKey as $keyword)
		{
			if (isset($_SERVER[$keyword])) return $_SERVER[$keyword];
			elseif (isset( $_ENV[$keyword])) return $_ENV[$keyword];
			elseif (@getenv($keyword)) return @getenv($keyword);
			elseif (function_exists('apache_getenv') AND apache_getenv($keyword, true)) return apache_getenv($keyword, true);
		}
		return '';
	}

	private function _unhtmlentities($value) {
		$value = preg_replace("/%3A%2F%2F/", '', $value);
		$value = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $value);
		$value = preg_replace("/%u0([a-z0-9]{3})/i", "&#x\\1;", $value);
		$value = preg_replace("/%([a-z0-9]{2})/i", "&#x\\1;", $value);
		$value = str_ireplace(array('&#x53;&#x43;&#x52;&#x49;&#x50;&#x54;', '&#x26;&#x23;&#x78;&#x36;&#x41;&#x3B;&#x26;&#x23;&#x78;&#x36;&#x31;&#x3B;&#x26;&#x23;&#x78;&#x37;&#x36;&#x3B;&#x26;&#x23;&#x78;&#x36;&#x31;&#x3B;&#x26;&#x23;&#x78;&#x37;&#x33;&#x3B;&#x26;&#x23;&#x78;&#x36;&#x33;&#x3B;&#x26;&#x23;&#x78;&#x37;&#x32;&#x3B;&#x26;&#x23;&#x78;&#x36;&#x39;&#x3B;&#x26;&#x23;&#x78;&#x37;&#x30;&#x3B;&#x26;&#x23;&#x78;&#x37;&#x34;&#x3B;', '/*', '*/', '<!--', '-->', '<!-- -->', '&#x0A;', '&#x0D;', '&#x09;', '' ), '', $value);
		$search = '/&#[xX]0{0,8}(21|22|23|24|25|26|27|28|29|2a|2b|2d|2f|30|31|32|33|34|35|36|37|38|39|3a|3b|3d|3f|40|41|42|43|44|45|46|47|48|49|4a|4b|4c|4d|4e|4f|50|51|52|53|54|55|56|57|58|59|5a|5b|5c|5d|5e|5f|60|61|62|63|64|65|66|67|68|69|6a|6b|6c|6d|6e|6f|70|71|72|73|74|75|76|77|78|79|7a|7b|7c|7d|7e);?/ie';
		$value = preg_replace($search, "chr(hexdec('\\1'))", $value);
		$search = '/&#0{0,8}(33|34|35|36|37|38|39|40|41|42|43|45|47|48|49|50|51|52|53|54|55|56|57|58|59|61|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126);?/ie';
		$value = preg_replace($search, "chr('\\1')", $value);
		$search = array('&#60', '&#060', '&#0060', '&#00060', '&#000060', '&#0000060', '&#60;', '&#060;', '&#0060;', '&#00060;', '&#000060;', '&#0000060;', '&#x3c', '&#x03c', '&#x003c', '&#x0003c', '&#x00003c', '&#x000003c', '&#x3c;', '&#x03c;', '&#x003c;', '&#x0003c;', '&#x00003c;', '&#x000003c;', '&#X3c', '&#X03c', '&#X003c', '&#X0003c', '&#X00003c', '&#X000003c', '&#X3c;', '&#X03c;', '&#X003c;', '&#X0003c;', '&#X00003c;', '&#X000003c;', '&#x3C', '&#x03C', '&#x003C', '&#x0003C', '&#x00003C', '&#x000003C', '&#x3C;', '&#x03C;', '&#x003C;', '&#x0003C;', '&#x00003C;', '&#x000003C;', '&#X3C', '&#X03C', '&#X003C', '&#X0003C', '&#X00003C', '&#X000003C', '&#X3C;', '&#X03C;', '&#X003C;', '&#X0003C;', '&#X00003C;', '&#X000003C;', '\x3c', '\x3C', '\u003c', '\u003C');
		$value = str_ireplace($search, '<', $value);
		return $value;
	}
}